package monitor_platon

import (
	"encoding/json"
	"errors"
	platon "github.com/PlatONnetwork/PlatON-Go"
	"github.com/PlatONnetwork/PlatON-Go/common"
	contract "github.com/PlatONnetwork/PlatON-Go/core/vm"
	"github.com/PlatONnetwork/PlatON-Go/p2p/discover"
	"go.uber.org/zap"
	"math/big"
	go_logger "platon-tools/go-service/go-logger"
	"platon-tools/go-service/monitor/utile"
)

// 当前节点的质押信息
//
func (s *Node) getCandidateInfo(nodeId []byte) (*utile.CandidateHex, error) {
	result, err := s.call(contract.QueryCandidateInfo, nodeId)
	if err != nil {
		go_logger.Logger.Error("getCandidateInfo", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  *utile.CandidateHex
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("getCandidateInfo failed no error")
}

//func (s *Node) getCandidateInfoByByte(nodeId discover.NodeID) (*utile.CandidateHex, error) {
//	result, err := s.call(contract.QueryCandidateInfo, nodeId)
//	if err != nil {
//		go_logger.Logger.Error("getCandidateInfo", zap.Error(err))
//		return nil, err
//	}
//
//	if result != nil {
//		type Result struct {
//			Code uint32
//			Ret  *utile.CandidateHex
//		}
//		var res Result
//		if err := json.Unmarshal(result, &res); err != nil {
//			go_logger.Logger.Error("unmarshal result", zap.Error(err))
//			return nil, err
//		} else {
//			return res.Ret, nil
//		}
//	}
//
//	return nil, errors.New("getCandidateInfo failed no error")
//}

func (s *Node) getCurrentCyclePackageReward() (*string, error) {
	result, err := s.call(contract.GetPackageReward)
	if err != nil {
		go_logger.Logger.Error("GetPackageReward", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  *string
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("GetPackageReward failed no error")
}

// 当前结算周期的质押奖励
func (s *Node) getCurrentCycleStakingReward() (*string, error) {
	result, err := s.call(contract.GetStakingReward)
	if err != nil {
		go_logger.Logger.Error("GetStakingReward", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  *string
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("GetStakingReward failed no error")
}

// 当前结算周期的验证人队列  结算周期过了才变
// 查询当前结算周期的验证人信息。每个结算周期结束都会根据所有候选验证人的总权重更新下个结算周期的验证人列表
func (s *Node) getCurrentCycleVerifierList() (utile.ValidatorExQueue, error) {
	result, err := s.call(contract.QueryVerifierList)
	if err != nil {
		go_logger.Logger.Error("QueryVerifierList", zap.Error(err))
		return nil, err
	}

	if err != nil {
		go_logger.Logger.Error("call", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  utile.ValidatorExQueue
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("QueryVerifierList failed no error")
}

// 当前共识周期的验证人列表 43
// 该接口用来查询当前共识周期被选中出块的验证人列表。每个共识轮为430个块，在410块的时候会从当前结算周期的验证人队列中产生下个共识轮可以参与出块的验证人列表
func (s *Node) getCurrentConsensusValidatorList() (utile.ValidatorExQueue, error) {
	result, err := s.call(contract.QueryValidatorList)
	if err != nil {
		go_logger.Logger.Error("QueryValidatorList", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  utile.ValidatorExQueue
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("QueryValidatorList failed no error")
}

// 所有实时的候选人列表
// 该接口用来查询所有候选验证人信息列表，任何成功质押的节点都是候选验证人
func (s *Node) getCurrentCandidateList() (utile.CandidateHexQueue, error) {
	result, err := s.call(contract.QueryCandidateList)
	if err != nil {
		go_logger.Logger.Error("QueryCandidateList", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  utile.CandidateHexQueue
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("QueryCandidateList failed no error")
}

// 查询的节点的当前账户地址所委托NodeID和质押Id
/*
	String：address 委托人的账户地址
	String：nodeId 验证人的节点Id
	BigInteger：stakingBlockNum 发起质押时的区块高度

*/
func (s *Node) getRelatedListByDelAddr(addr common.Address) (utile.DelRelatedQueue, error) {
	result, err := s.call(contract.QueryRelateList, addr.Bytes())
	if err != nil {
		go_logger.Logger.Error("QueryRelateList", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  utile.DelRelatedQueue
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("QueryRelateList failed no error")
}

// 查询当前单个委托信息
func (s *Node) getDelegateInfo(addr common.Address, id discover.NodeID, stakingBN *big.Int) (*utile.DelegateRelated, error) {
	result, err := s.call(contract.QueryDelegateInfo, addr.Bytes(), id.Bytes(), stakingBN.Bytes())
	if err != nil {
		go_logger.Logger.Error("QueryDelegateInfo", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  *utile.DelegateRelated
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("QueryDelegateInfo failed no error")
}

func (s *Node) getTallyResult() (*utile.DelegateRelated, error) {
	result, err := s.call(contract.QueryRestrictingInfo)
	if err != nil {
		go_logger.Logger.Error("QueryDelegateInfo", zap.Error(err))
		return nil, err
	}

	if result != nil {
		type Result struct {
			Code uint32
			Ret  *utile.DelegateRelated
		}
		var res Result
		if err := json.Unmarshal(result, &res); err != nil {
			go_logger.Logger.Error("unmarshal result", zap.Error(err))
			return nil, err
		} else {
			return res.Ret, nil
		}
	}

	return nil, errors.New("QueryDelegateInfo failed no error")
}

func (s *Node) call(info uint16, args ...[]byte) ([]byte, error) {
	var (
		data []byte
		to   common.Address
	)
	if len(args) > 0 {
		data, to = encodePPOS(info, args...)
	} else {
		data, to = encodePPOS(info)
	}

	var msg platon.CallMsg

	msg.Data = data
	msg.To = &to
	msg.From = s.from
	return s.Client.CallContract(s.ctx, msg, nil)
}
